/*
 * XXX
 */

package edu.uhcl.csci4838.group3.database;

import java.util.Map.Entry;
import java.util.Set;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteCursor;
import android.database.sqlite.SQLiteCursorDriver;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQuery;
import android.util.Log;
import edu.uhcl.csci4838.group3.database.info.Course;
import edu.uhcl.csci4838.group3.database.info.CourseAlert;
import edu.uhcl.csci4838.group3.database.info.CourseCategoryWeight;
import edu.uhcl.csci4838.group3.database.info.CourseFaculty;
import edu.uhcl.csci4838.group3.database.info.CourseTimeOverride;
import edu.uhcl.csci4838.group3.database.info.Department;
import edu.uhcl.csci4838.group3.database.info.Faculty;
import edu.uhcl.csci4838.group3.database.info.FacultyEmail;
import edu.uhcl.csci4838.group3.database.info.FacultyPhone;
import edu.uhcl.csci4838.group3.database.info.GradingScale;
import edu.uhcl.csci4838.group3.database.info.GradingScaleRange;
import edu.uhcl.csci4838.group3.database.info.Holiday;
import edu.uhcl.csci4838.group3.database.info.OfficeHours;
import edu.uhcl.csci4838.group3.database.info.Semester;
import edu.uhcl.csci4838.group3.database.info.Task;
import edu.uhcl.csci4838.group3.database.info.TaskAlert;
import edu.uhcl.csci4838.group3.pendingIntents.AllIntents;
import edu.uhcl.csci4838.group3.pendingIntents.notifications.ReminderMngr;
import edu.uhcl.csci4838.group3.pendingIntents.ringer.RingerIntent;

/**
 * This class contains methods and custom Cursor objects to add, delete, edit,
 * and query the database.
 * 
 * @author Kiet Nguyen
 */
public class BackpackEduDatabaseHelper extends SQLiteOpenHelper {
	
	/**
	 * @author Kiet Nguyen The CursorCourse object (which is a dataset) that is
	 *         returned by calling the getCourse method. Each row of the dataset
	 *         is a record in the Course table that meets the query criteria
	 *         passed to the getCourse method. This class provides you all the
	 *         get methods you need to access the values of the rows in the
	 *         dataset. Use the getCount() to determine how many rows was
	 *         returned and moveToPosition() method to traverse the rows
	 */
	public static class CursorCourse extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorCourse(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ Course.TABLE_NAME
				+ " ";
		
		private CursorCourse(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public int getColDayBitField() {
			return this.getInt(this.getColumnIndexOrThrow(Course.DAY_BIT_FIELD));
		}
		
		public String getColDescription() {
			return this.getString(this.getColumnIndexOrThrow(Course.DESCRIPTION));
		}
		
		public Long getColEndDate() {
			if (this.isNull(this.getColumnIndexOrThrow(Course.END_DATE))) {
				return null;
			}
			return this.getLong(this.getColumnIndexOrThrow(Course.END_DATE));
		}
		
		public Integer getColEndTimeHour() {
			if (this.isNull(this.getColumnIndexOrThrow(Course.END_TIME_HOUR))) {
				return null;
			}
			return this.getInt(this.getColumnIndexOrThrow(Course.END_TIME_HOUR));
		}
		
		public Integer getColEndTimeMinute() {
			if (this.isNull(this.getColumnIndexOrThrow(Course.END_TIME_MINUTE))) {
				return null;
			}
			return this.getInt(this.getColumnIndexOrThrow(Course.END_TIME_MINUTE));
		}
		
		public String getColGradeScaleName() {
			return this.getString(this.getColumnIndexOrThrow(Course.GRADE_SCALE_NAME));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(Course.ID));
		}
		
		public String getColLocation() {
			return this.getString(this.getColumnIndexOrThrow(Course.LOCATION));
		}
		
		public String getColName() {
			return this.getString(this.getColumnIndexOrThrow(Course.NAME));
		}
		
		public String getColRssFeed() {
			return this.getString(this.getColumnIndexOrThrow(Course.RSS_FEED));
		}
		
		public long getColSemesterId() {
			return this.getLong(this.getColumnIndexOrThrow(Course.SEMESTER_ID));
		}
		
		public String getColSemesterName() {
			return this.getString(this.getColumnIndexOrThrow(Course.SEMESTER_NAME));
		}
		
		public Long getColStartDate() {
			if (this.isNull(this.getColumnIndexOrThrow(Course.START_DATE))) {
				return null;
			}
			
			return this.getLong(this.getColumnIndexOrThrow(Course.START_DATE));
		}
		
		public Integer getColStartTimeHour() {
			if (this.isNull(this.getColumnIndexOrThrow(Course.START_TIME_HOUR))) {
				return null;
			}
			return this.getInt(this.getColumnIndexOrThrow(Course.START_TIME_HOUR));
		}
		
		public Integer getColStartTimeMinute() {
			if (this.isNull(this.getColumnIndexOrThrow(Course.START_TIME_MINUTE))) {
				return null;
			}
			return this.getInt(this.getColumnIndexOrThrow(Course.START_TIME_MINUTE));
		}
		
		public String getColWebsite() {
			return this.getString(this.getColumnIndexOrThrow(Course.WEBSITE));
		}
	}
	
	/**
	 * @author Kiet Nguyen The CursorCourseAlert object (which is a dataset)
	 *         that is returned by calling the getCourseAlert method. Each row
	 *         of the dataset is a record in the CourseAlert table that meets
	 *         the query criteria passed to the getCourseAlert method. This
	 *         class provides you all the get methods you need to access the
	 *         values of the rows in the dataset. Use the getCount() to
	 *         determine how many rows was returned and moveToPosition() method
	 *         to traverse the rows
	 */
	public static class CursorCourseAlert extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorCourseAlert(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ CourseAlert.TABLE_NAME
				+ " ";
		
		private CursorCourseAlert(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public long getColCourseId() {
			return this.getLong(this.getColumnIndexOrThrow(CourseAlert.COURSE_ID));
		}
		
		public String getColCourseName() {
			return this.getString(this.getColumnIndexOrThrow(CourseAlert.COURSE_NAME));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(CourseAlert.ID));
		}
		
		public int getColMinutesBefore() {
			return this.getInt(this.getColumnIndexOrThrow(CourseAlert.MINUTES_BEFORE));
		}
		
		public String getColSemesterName() {
			return this.getString(this.getColumnIndexOrThrow(CourseAlert.SEMESTER_NAME));
		}
	}
	
	/**
	 * @author Kiet Nguyen The CursorCourseCategoryWeight object (which is a
	 *         dataset) that is returned by calling the getCourseCategoryWeight
	 *         method. Each row of the dataset is a record in the
	 *         CourseCategoryWeight table that meets the query criteria passed
	 *         to the getCourseCategoryWeight method. This class provides you
	 *         all the get methods you need to access the values of the rows in
	 *         the dataset. Use the getCount() to determine how many rows was
	 *         returned and moveToPosition() method to traverse the rows
	 */
	public static class CursorCourseCategoryWeight extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorCourseCategoryWeight(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ CourseCategoryWeight.TABLE_NAME
				+ " ";
		
		private CursorCourseCategoryWeight(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public String getColCategoryName() {
			return this.getString(this.getColumnIndexOrThrow(CourseCategoryWeight.CATEGORY_NAME));
		}
		
		public long getColCourseId() {
			return this.getLong(this.getColumnIndexOrThrow(CourseCategoryWeight.COURSE_ID));
		}
		
		public String getColCourseName() {
			return this.getString(this.getColumnIndexOrThrow(CourseCategoryWeight.COURSE_NAME));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(CourseCategoryWeight.ID));
		}
		
		public String getColSemesterName() {
			return this.getString(this.getColumnIndexOrThrow(CourseCategoryWeight.SEMESTER_NAME));
		}
		
		public Double getColWeight() {
			if (this.isNull(this.getColumnIndexOrThrow(CourseCategoryWeight.WEIGHT))) {
				return null;
			}
			return this.getDouble(this.getColumnIndexOrThrow(CourseCategoryWeight.WEIGHT));
		}
	}
	
	/**
	 * @author Kiet Nguyen The CursorCourseFaculty object (which is a dataset)
	 *         that is returned by calling the getCourseFaculty method. Each row
	 *         of the dataset is a record in the CourseFaculty table that meets
	 *         the query criteria passed to the getCourseFaculty method. This
	 *         class provides you all the get methods you need to access the
	 *         values of the rows in the dataset. Use the getCount() to
	 *         determine how many rows was returned and moveToPosition() method
	 *         to traverse the rows
	 */
	public static class CursorCourseFaculty extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorCourseFaculty(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ CourseFaculty.TABLE_NAME
				+ " ";
		
		private CursorCourseFaculty(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public long getColCourseId() {
			return this.getLong(this.getColumnIndexOrThrow(CourseFaculty.COURSE_ID));
		}
		
		public String getColCourseName() {
			return this.getString(this.getColumnIndexOrThrow(CourseFaculty.COURSE_NAME));
		}
		
		public String getColDepartmentName() {
			return this.getString(this.getColumnIndexOrThrow(CourseFaculty.DEPARTMENT_NAME));
		}
		
		public long getColFacultyId() {
			return this.getLong(this.getColumnIndexOrThrow(CourseFaculty.FACULTY_ID));
		}
		
		public String getColFacultyType() {
			return this.getString(this.getColumnIndexOrThrow(CourseFaculty.TYPE));
		}
		
		public String getColFirstName() {
			return this.getString(this.getColumnIndexOrThrow(CourseFaculty.FIRST_NAME));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(CourseFaculty.ID));
		}
		
		public String getColLastName() {
			return this.getString(this.getColumnIndexOrThrow(CourseFaculty.LAST_NAME));
		}
		
		public String getColSemesterName() {
			return this.getString(this.getColumnIndexOrThrow(CourseFaculty.SEMESTER_NAME));
		}
	}
	
	public static class CursorCoursesForAgendaView extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorCoursesForAgendaView(db,
						driver,
						editTable,
						query);
			}
		}
		
		private CursorCoursesForAgendaView(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public int getColDayBitField() {
			
			return this.getInt(this.getColumnIndexOrThrow(Course.DAY_BIT_FIELD));
		}
		
		public long getColEndDate() {
			
			return this.getLong(this.getColumnIndexOrThrow(Course.END_DATE));
		}
		
		public Integer getColEndTimeHour() {
			if (this.isNull(this.getColumnIndexOrThrow(Course.END_TIME_HOUR))) {
				return null;
			}
			return this.getInt(this.getColumnIndexOrThrow(Course.END_TIME_HOUR));
		}
		
		public Integer getColEndTimeMinute() {
			if (this.isNull(this.getColumnIndexOrThrow(Course.END_TIME_MINUTE))) {
				return null;
			}
			return this.getInt(this.getColumnIndexOrThrow(Course.END_TIME_MINUTE));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(Course.ID));
		}
		
		public String getColName() {
			return this.getString(this.getColumnIndexOrThrow(Course.NAME));
		}
		
		public long getColSemesterId() {
			return this.getLong(this.getColumnIndexOrThrow(Course.SEMESTER_ID));
		}
		
		public long getColStartDate() {
			
			return this.getLong(this.getColumnIndexOrThrow(Course.START_DATE));
		}
		
		public Integer getColStartTimeHour() {
			if (this.isNull(this.getColumnIndexOrThrow(Course.START_TIME_HOUR))) {
				return null;
			}
			return this.getInt(this.getColumnIndexOrThrow(Course.START_TIME_HOUR));
		}
		
		public Integer getColStartTimeMinute() {
			if (this.isNull(this.getColumnIndexOrThrow(Course.START_TIME_MINUTE))) {
				return null;
			}
			return this.getInt(this.getColumnIndexOrThrow(Course.START_TIME_MINUTE));
		}
		
	}
	
	/**
	 * @author Kiet Nguyen The CursorCourseTimeOverride object (which is a
	 *         dataset) that is returned by calling the getCourseTimeOverride
	 *         method. Each row of the dataset is a record in the
	 *         CourseTimeOverride table that meets the query criteria passed to
	 *         the getCourseTimeOverride method. This class provides you all the
	 *         get methods you need to access the values of the rows in the
	 *         dataset. Use the getCount() to determine how many rows was
	 *         returned and moveToPosition() method to traverse the rows
	 */
	public static class CursorCourseTimeOverride extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorCourseTimeOverride(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ CourseTimeOverride.TABLE_NAME
				+ " ";
		
		private CursorCourseTimeOverride(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public long getColCourseId() {
			return this.getLong(this.getColumnIndexOrThrow(CourseTimeOverride.COURSE_ID));
		}
		
		public String getColCourseName() {
			return this.getString(this.getColumnIndexOrThrow(CourseTimeOverride.COURSE_NAME));
		}
		
		public long getColDate() {
			return this.getLong(this.getColumnIndexOrThrow(CourseTimeOverride.DATE));
		}
		
		public int getColEndTimeHour() {
			return this.getInt(this.getColumnIndexOrThrow(CourseTimeOverride.END_TIME_HOUR));
		}
		
		public int getColEndTimeMinute() {
			return this.getInt(this.getColumnIndexOrThrow(CourseTimeOverride.END_TIME_MINUTE));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(CourseTimeOverride.ID));
		}
		
		public String getColSemesterName() {
			return this.getString(this.getColumnIndexOrThrow(CourseTimeOverride.SEMESTER_NAME));
		}
		
		public int getColStartTimeHour() {
			return this.getInt(this.getColumnIndexOrThrow(CourseTimeOverride.START_TIME_HOUR));
		}
		
		public int getColStartTimeMinute() {
			return this.getInt(this.getColumnIndexOrThrow(CourseTimeOverride.START_TIME_MINUTE));
		}
		
	}
	
	/**
	 * @author Kiet Nguyen The CursorDepartment object (which is a dataset) that
	 *         is returned by calling the getDepartment method. Each row of the
	 *         dataset is a record in the Department table that meets the query
	 *         criteria passed to the getDepartment method. This class provides
	 *         you all the get methods you need to access the values of the rows
	 *         in the dataset. Use the getCount() to determine how many rows was
	 *         returned and moveToPosition() method to traverse the rows
	 */
	public static class CursorDepartment extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorDepartment(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ Department.TABLE_NAME
				+ " ";
		
		private CursorDepartment(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(Department.ID));
		}
		
		public String getColName() {
			return this.getString(this.getColumnIndexOrThrow(Department.NAME));
		}
	}
	
	/**
	 * @author Kiet Nguyen The CursorFaculty object (which is a dataset) that is
	 *         returned by calling the getFaculty method. Each row of the
	 *         dataset is a record in the Faculty table that meets the query
	 *         criteria passed to the getFaculty method. This class provides you
	 *         all the get methods you need to access the values of the rows in
	 *         the dataset. Use the getCount() to determine how many rows was
	 *         returned and moveToPosition() method to traverse the rows
	 */
	public static class CursorFaculty extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorFaculty(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ Faculty.TABLE_NAME
				+ " ";
		
		private CursorFaculty(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public String getColDepartmentName() {
			return this.getString(this.getColumnIndexOrThrow(Faculty.DEPARTMENT_NAME));
		}
		
		public String getColFirstName() {
			return this.getString(this.getColumnIndexOrThrow(Faculty.FIRST_NAME));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(Faculty.ID));
		}
		
		public String getColLastName() {
			return this.getString(this.getColumnIndexOrThrow(Faculty.LAST_NAME));
		}
		
		public String getColWebsite() {
			return this.getString(this.getColumnIndexOrThrow(Faculty.WEBSITE));
		}
		
	}
	
	/**
	 * @author Kiet Nguyen The CursorFacultyEmail object (which is a dataset)
	 *         that is returned by calling the getCursorFacultyEmail method.
	 *         Each row of the dataset is a record in the CursorFacultyEmail
	 *         table that meets the query criteria passed to the
	 *         getCursorFacultyEmail method. This class provides you all the get
	 *         methods you need to access the values of the rows in the dataset.
	 *         Use the getCount() to determine how many rows was returned and
	 *         moveToPosition() method to traverse the rows
	 */
	public static class CursorFacultyEmail extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorFacultyEmail(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ FacultyEmail.TABLE_NAME
				+ " ";
		
		private CursorFacultyEmail(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public String getColDepartmentName() {
			return this.getString(this.getColumnIndexOrThrow(FacultyEmail.DEPARTMENT_NAME));
		}
		
		public String getColEmailAddress() {
			return this.getString(this.getColumnIndexOrThrow(FacultyEmail.EMAIL_ADDRESS));
		}
		
		public long getColFacultyId() {
			return this.getLong(this.getColumnIndexOrThrow(FacultyEmail.FACULTY_ID));
		}
		
		public String getColFirstName() {
			return this.getString(this.getColumnIndexOrThrow(FacultyEmail.FIRST_NAME));
		}
		
		public String getColLabel() {
			return this.getString(this.getColumnIndexOrThrow(FacultyEmail.LABEL));
		}
		
		public String getColLastName() {
			return this.getString(this.getColumnIndexOrThrow(FacultyEmail.LAST_NAME));
		}
		
	}
	
	/**
	 * @author Kiet Nguyen The CursorFacultyPhone object (which is a dataset)
	 *         that is returned by calling the getFacultyPhone method. Each row
	 *         of the dataset is a record in the FacultyPhone table that meets
	 *         the query criteria passed to the getFacultyPhone method. This
	 *         class provides you all the get methods you need to access the
	 *         values of the rows in the dataset. Use the getCount() to
	 *         determine how many rows was returned and moveToPosition() method
	 *         to traverse the rows
	 */
	public static class CursorFacultyPhone extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorFacultyPhone(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ FacultyPhone.TABLE_NAME
				+ " ";
		
		private CursorFacultyPhone(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public String getColDepartmentName() {
			return this.getString(this.getColumnIndexOrThrow(FacultyPhone.DEPARTMENT_NAME));
		}
		
		public long getColFacultyId() {
			return this.getLong(this.getColumnIndexOrThrow(FacultyPhone.FACULTY_ID));
		}
		
		public String getColFirstName() {
			return this.getString(this.getColumnIndexOrThrow(FacultyPhone.FIRST_NAME));
		}
		
		public String getColLabel() {
			return this.getString(this.getColumnIndexOrThrow(FacultyPhone.LABEL));
		}
		
		public String getColLastName() {
			return this.getString(this.getColumnIndexOrThrow(FacultyPhone.LAST_NAME));
		}
		
		public String getColPhoneNumber() {
			return this.getString(this.getColumnIndexOrThrow(FacultyPhone.PHONE_NUMBER));
		}
		
	}
	
	/**
	 * @author Kiet Nguyen The CursorGradingScale object (which is a dataset)
	 *         that is returned by calling the getGradingScale method. Each row
	 *         of the dataset is a record in the GradingScale table that meets
	 *         the query criteria passed to the getGradingScale method. This
	 *         class provides you all the get methods you need to access the
	 *         values of the rows in the dataset. Use the getCount() to
	 *         determine how many rows was returned and moveToPosition() method
	 *         to traverse the rows
	 */
	public static class CursorGradingScale extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorGradingScale(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ GradingScale.TABLE_NAME
				+ " ";
		
		private CursorGradingScale(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(GradingScaleRange.ID));
		}
		
		public String getColName() {
			return this.getString(this.getColumnIndexOrThrow(GradingScale.NAME));
		}
		
	}
	
	/**
	 * @author Kiet Nguyen The CursorGradingScaleRange object (which is a
	 *         dataset) that is returned by calling the getGradingScaleRange
	 *         method. Each row of the dataset is a record in the
	 *         GradingScaleRange table that meets the query criteria passed to
	 *         the getGradingScaleRange method. This class provides you all the
	 *         get methods you need to access the values of the rows in the
	 *         dataset. Use the getCount() to determine how many rows was
	 *         returned and moveToPosition() method to traverse the rows
	 */
	public static class CursorGradingScaleRange extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorGradingScaleRange(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ GradingScaleRange.TABLE_NAME
				+ " ";
		
		private CursorGradingScaleRange(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(GradingScaleRange.ID));
		}
		
		public String getColLetterGrade() {
			return this.getString(this.getColumnIndexOrThrow(GradingScaleRange.LETTER_GRADE));
		}
		
		public double getColMinValue() {
			return this.getDouble(this.getColumnIndexOrThrow(GradingScaleRange.MIN_VALUE));
		}
		
		public String getColName() {
			return this.getString(this.getColumnIndexOrThrow(GradingScaleRange.NAME));
		}
		
	}
	
	/**
	 * @author Kiet Nguyen The CursorHoliday object (which is a dataset) that is
	 *         returned by calling the getHoliday method. Each row of the
	 *         dataset is a record in the Holiday table that meets the query
	 *         criteria passed to the getHoliday method. This class provides you
	 *         all the get methods you need to access the values of the rows in
	 *         the dataset. Use the getCount() to determine how many rows was
	 *         returned and moveToPosition() method to traverse the rows
	 */
	public static class CursorHoliday extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorHoliday(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ Holiday.TABLE_NAME
				+ " ";
		
		private CursorHoliday(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public long getColEndDate() {
			return this.getLong(this.getColumnIndexOrThrow(Holiday.END_DATE));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(Holiday.ID));
		}
		
		public String getColName() {
			return this.getString(this.getColumnIndexOrThrow(Holiday.NAME));
		}
		
		public long getColSemesterId() {
			return this.getLong(this.getColumnIndexOrThrow(Holiday.SEMESTER_ID));
		}
		
		public String getColSemesterName() {
			return this.getString(this.getColumnIndexOrThrow(Holiday.SEMESTER_NAME));
		}
		
		public long getColStartDate() {
			return this.getLong(this.getColumnIndexOrThrow(Holiday.START_DATE));
		}
	}
	
	/**
	 * @author Kiet Nguyen The CursorOfficeHours object (which is a dataset)
	 *         that is returned by calling the getOfficeHours method. Each row
	 *         of the dataset is a record in the OfficeHours table that meets
	 *         the query criteria passed to the getOfficeHours method. This
	 *         class provides you all the get methods you need to access the
	 *         values of the rows in the dataset. Use the getCount() to
	 *         determine how many rows was returned and moveToPosition() method
	 *         to traverse the rows
	 */
	public static class CursorOfficeHours extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorOfficeHours(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ OfficeHours.TABLE_NAME
				+ " ";
		
		private CursorOfficeHours(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public long getColCourseId() {
			return this.getLong(this.getColumnIndexOrThrow(OfficeHours.COURSE_ID));
		}
		
		public String getColCourseName() {
			return this.getString(this.getColumnIndexOrThrow(OfficeHours.COURSE_NAME));
		}
		
		public int getColDay() {
			return this.getInt(this.getColumnIndexOrThrow(OfficeHours.DAY));
		}
		
		public String getColDepartmentName() {
			return this.getString(this.getColumnIndexOrThrow(OfficeHours.DEPARTMENT_NAME));
		}
		
		public String getColEndTime() {
			return this.getString(this.getColumnIndexOrThrow(OfficeHours.END_TIME));
		}
		
		public long getColFacultyId() {
			return this.getLong(this.getColumnIndexOrThrow(OfficeHours.FACULTY_ID));
		}
		
		public String getColFirstName() {
			return this.getString(this.getColumnIndexOrThrow(OfficeHours.FIRST_NAME));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(OfficeHours.ID));
		}
		
		public String getColLastName() {
			return this.getString(this.getColumnIndexOrThrow(OfficeHours.LAST_NAME));
		}
		
		public String getColLocation() {
			return this.getString(this.getColumnIndexOrThrow(OfficeHours.LOCATION));
		}
		
		public String getColSemesterName() {
			return this.getString(this.getColumnIndexOrThrow(OfficeHours.SEMESTER_NAME));
		}
		
		public String getColStartTime() {
			return this.getString(this.getColumnIndexOrThrow(OfficeHours.START_TIME));
		}
	}
	
	/**
	 * @author Kiet Nguyen The CursorSemester object (which is a dataset) that
	 *         is returned by calling the getSemester method. Each row of the
	 *         dataset is a record in the Semester table that meets the query
	 *         criteria passed to the getSemester method. This class provides
	 *         you all the get methods you need to access the values of the rows
	 *         in the dataset. Use the getCount() to determine how many rows was
	 *         returned and moveToPosition() method to traverse the rows
	 */
	public static class CursorSemester extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorSemester(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ Semester.TABLE_NAME
				+ " ";
		
		private CursorSemester(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(Course.ID));
		}
		
		public String getColName() {
			return this.getString(this.getColumnIndexOrThrow(Semester.NAME));
		}
		
		public Long getColTimeCreated() {
			return this.getLong(this.getColumnIndexOrThrow(Semester.CREATION_DATE));
		}
	}
	
	/**
	 * @author Kiet Nguyen The CursorTask object (which is a dataset) that is
	 *         returned by calling the getTask method. Each row of the dataset
	 *         is a record in the Task table that meets the query criteria
	 *         passed to the getTask method. This class provides you all the get
	 *         methods you need to access the values of the rows in the dataset.
	 *         Use the getCount() to determine how many rows was returned and
	 *         moveToPosition() method to traverse the rows
	 */
	public static class CursorTask extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorTask(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ Task.TABLE_NAME
				+ " ";
		
		private CursorTask(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public String getColCategoryName() {
			return this.getString(this.getColumnIndexOrThrow(Task.CATEGORY_NAME));
		}
		
		public long getColCourseId() {
			return this.getLong(this.getColumnIndexOrThrow(Task.COURSE_ID));
		}
		
		public String getColCourseName() {
			return this.getString(this.getColumnIndexOrThrow(Task.COURSE_NAME));
		}
		
		public Long getColDateDue() {
			if (this.isNull(this.getColumnIndexOrThrow(Task.DATE_DUE))) {
				return null;
			}
			return this.getLong(this.getColumnIndexOrThrow(Task.DATE_DUE));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(Task.ID));
		}
		
		public boolean getColIsCompleted() {
			final int isCompleted = this.getInt(this.getColumnIndexOrThrow(Task.IS_COMPLETED));
			if (isCompleted == 0) {
				return false;
			}
			return true;
		}
		
		public Double getColMaxGrade() {
			return this.getDouble(this.getColumnIndexOrThrow(Task.MAX_GRADE));
		}
		
		public String getColName() {
			return this.getString(this.getColumnIndexOrThrow(Task.NAME));
		}
		
		public Double getColReceivedGrade() {
			if (this.isNull(this.getColumnIndexOrThrow(Task.RECEIVED_GRADE))) {
				return null;
			}
			return this.getDouble(this.getColumnIndexOrThrow(Task.RECEIVED_GRADE));
		}
		
		public String getColSemesterName() {
			return this.getString(this.getColumnIndexOrThrow(Task.SEMESTER_NAME));
		}
		
		public Double getColWeightOverride() {
			if (this.isNull(this.getColumnIndexOrThrow(Task.WEIGHT_OVERRIDE))) {
				return null;
			}
			return this.getDouble(this.getColumnIndexOrThrow(Task.WEIGHT_OVERRIDE));
		}
		
	}
	
	/**
	 * @author Kiet Nguyen The CursorTaskAlert object (which is a dataset) that
	 *         is returned by calling the getTaskAlert method. Each row of the
	 *         dataset is a record in the TaskAlert table that meets the query
	 *         criteria passed to the getTaskAlert method. This class provides
	 *         you all the get methods you need to access the values of the rows
	 *         in the dataset. Use the getCount() to determine how many rows was
	 *         returned and moveToPosition() method to traverse the rows
	 */
	public static class CursorTaskAlert extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorTaskAlert(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT * FROM "
				+ TaskAlert.TABLE_NAME
				+ " ";
		
		private CursorTaskAlert(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public String getColCategoryName() {
			return this.getString(this.getColumnIndexOrThrow(TaskAlert.CATEGORY_NAME));
		}
		
		public String getColCourseName() {
			return this.getString(this.getColumnIndexOrThrow(TaskAlert.COURSE_NAME));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(TaskAlert.ID));
		}
		
		public int getColMinutesBefore() {
			return this.getInt(this.getColumnIndexOrThrow(TaskAlert.MINUTES_BEFORE));
		}
		
		public String getColSemesterName() {
			return this.getString(this.getColumnIndexOrThrow(TaskAlert.SEMESTER_NAME));
		}
		
		public long getColTaskId() {
			return this.getLong(this.getColumnIndexOrThrow(TaskAlert.TASK_ID));
		}
		
		public String getColTaskName() {
			return this.getString(this.getColumnIndexOrThrow(TaskAlert.TASK_NAME));
		}
	}
	
	public static class CursorTaskForAgendaView extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorTaskForAgendaView(db,
						driver,
						editTable,
						query);
			}
		}
		
		private CursorTaskForAgendaView(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public long getColCourseId() {
			return this.getLong(this.getColumnIndexOrThrow(Task.COURSE_ID));
		}
		
		public String getColCourseName() {
			return this.getString(this.getColumnIndexOrThrow(Task.COURSE_NAME));
		}
		
		public Long getColDateDue() {
			if (this.isNull(this.getColumnIndexOrThrow(Task.DATE_DUE))) {
				return null;
			}
			return this.getLong(this.getColumnIndexOrThrow(Task.DATE_DUE));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(Task.ID));
		}
		
		public boolean getColIsCompleted() {
			final int isCompleted = this.getInt(this.getColumnIndexOrThrow(Task.IS_COMPLETED));
			if (isCompleted == 0) {
				return false;
			}
			return true;
		}
		
		public String getColName() {
			return this.getString(this.getColumnIndexOrThrow(Task.NAME));
		}
		
	}
	
	public static class CursorUniqueFacultyType extends SQLiteCursor {
		
		private static class Factory implements SQLiteDatabase.CursorFactory {
			@Override
			public Cursor newCursor(final SQLiteDatabase db,
					final SQLiteCursorDriver driver,
					final String editTable,
					final SQLiteQuery query) {
				return new CursorUniqueFacultyType(db,
						driver,
						editTable,
						query);
			}
		}
		
		private static final String QUERY = "SELECT DISTINCT "
				+ CourseFaculty.TYPE
				+ " AS "
				+ CourseFaculty.TYPE
				+ ", "
				+ CourseFaculty.ID
				+ " FROM "
				+ CourseFaculty.TABLE_NAME
				+ " ";
		
		private CursorUniqueFacultyType(final SQLiteDatabase db,
				final SQLiteCursorDriver driver,
				final String editTable,
				final SQLiteQuery query) {
			super(db,
					driver,
					editTable,
					query);
		}
		
		public String getColType() {
			return this.getString(this.getColumnIndexOrThrow(CourseFaculty.TYPE));
		}
		
		public long getColId() {
			return this.getLong(this.getColumnIndexOrThrow(CourseCategoryWeight.ID));
		}
		
	}
	
	private static String dbInitilizer = "PRAGMA foreign_keys = ON;\n"
			+
			
			"CREATE TABLE Semester (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, creationDate INTEGER);\n"
			+ "CREATE UNIQUE INDEX SemesterIndex1 ON Semester(name);\n"
			+
			
			"CREATE TABLE Course (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, semesterId INTEGER REFERENCES Semester(_id) ON DELETE CASCADE ON UPDATE CASCADE, semesterName TEXT REFERENCES Semester(name) ON DELETE CASCADE ON UPDATE CASCADE, description TEXT, location TEXT, website TEXT, rssFeed TEXT, dayBitField INTEGER, startTimeHour INTEGER, startTimeMinute INTEGER, endTimeHour INTEGER, endTimeMinute INTEGER, startDate INTEGER, endDate INTEGER, gradeScaleName TEXT REFERENCES GradingScale(name) ON DELETE CASCADE ON UPDATE CASCADE);\n"
			+ "CREATE UNIQUE INDEX CourseIndex1 ON Course(name, semesterName);\n"
			+
			
			"CREATE TABLE CourseCategoryWeight (_id INTEGER PRIMARY KEY AUTOINCREMENT, courseId INTEGER REFERENCES Course(_id) ON DELETE CASCADE ON UPDATE CASCADE, categoryName TEXT, courseName TEXT, semesterName TEXT, weight REAL, FOREIGN KEY (courseName, semesterName) REFERENCES Course(name, semesterName) ON DELETE CASCADE ON UPDATE CASCADE);\n"
			+ "CREATE UNIQUE INDEX CourseCategoryWeightIndex1 ON CourseCategoryWeight(courseName, semesterName, categoryName);\n"
			+ "CREATE UNIQUE INDEX CourseCategoryWeightIndex2 ON CourseCategoryWeight(courseId, categoryName);\n"
			+
			
			"CREATE TABLE Task (_id INTEGER PRIMARY KEY AUTOINCREMENT, courseId INTEGER REFERENCES Course(_id) ON DELETE CASCADE ON UPDATE CASCADE, name TEXT, courseName TEXT, semesterName TEXT, categoryName TEXT, dateDue INTEGER, maxGrade REAL, receivedGrade REAL, isCompleted INTEGER DEFAULT 0, weightOverride REAL, FOREIGN KEY (courseName, semesterName, categoryName) REFERENCES CourseCategoryWeight(courseName, semesterName, categoryName) ON DELETE CASCADE ON UPDATE CASCADE);\n"
			+ "CREATE UNIQUE INDEX TaskIndex1 ON Task(name, courseName, semesterName, categoryName);\n"
			+ "CREATE UNIQUE INDEX TaskIndex2 ON Task(_id, courseId, categoryName);\n"
			+
			
			"CREATE TABLE Department (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT);\n"
			+ "CREATE UNIQUE INDEX DepartmentIndex1 ON Department(name);\n"
			+
			
			"CREATE TABLE Faculty (_id INTEGER PRIMARY KEY AUTOINCREMENT, firstName TEXT, lastName TEXT, departmentName TEXT REFERENCES Department(name) ON DELETE CASCADE ON UPDATE CASCADE, website TEXT);\n"
			+ "CREATE UNIQUE INDEX FacultyIndex1 ON Faculty(firstName, lastName, departmentName);\n"
			+
			
			"CREATE TABLE CourseFaculty (_id INTEGER PRIMARY KEY AUTOINCREMENT, courseId INTEGER REFERENCES Course(_id) ON DELETE CASCADE ON UPDATE CASCADE, facultyId INTEGER REFERENCES Faculty (_id) ON DELETE CASCADE ON UPDATE CASCADE, courseName TEXT, semesterName TEXT, firstName TEXT, lastName TEXT, departmentName TEXT, type TEXT, FOREIGN KEY (courseName, semesterName) REFERENCES Course(name, semesterName) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (firstName, lastName, departmentName) REFERENCES Faculty(firstName, lastName, departmentName) ON DELETE CASCADE ON UPDATE CASCADE);\n"
			+ "CREATE UNIQUE INDEX CourseFacultyIndex1 ON CourseFaculty(courseName, semesterName, firstName, lastName, departmentName);\n"
			+ "CREATE UNIQUE INDEX CourseFacultyIndex2 ON CourseFaculty(courseId, facultyId);\n"
			+
			
			"CREATE TABLE FacultyPhone (_id INTEGER PRIMARY KEY AUTOINCREMENT, facultyId INTEGER REFERENCES Faculty (_id) ON DELETE CASCADE ON UPDATE CASCADE, firstName TEXT, lastName TEXT, departmentName TEXT, phoneNumber TEXT, label TEXT, FOREIGN KEY (firstName, lastName, departmentName) REFERENCES Faculty (firstName, lastName, departmentName) ON DELETE CASCADE ON UPDATE CASCADE);\n"
			+ "CREATE UNIQUE INDEX FacultyPhoneIndex1 ON  FacultyPhone(firstName, lastName, departmentName, phoneNumber);\n"
			+ "CREATE UNIQUE INDEX FacultyPhoneIndex2 ON  FacultyPhone(facultyId, phoneNumber);\n"
			+
			
			"CREATE TABLE FacultyEmail (_id INTEGER PRIMARY KEY AUTOINCREMENT, facultyId INTEGER REFERENCES Faculty (_id) ON DELETE CASCADE ON UPDATE CASCADE, firstName TEXT, lastName TEXT, departmentName TEXT, emailAddress TEXT, label TEXT, FOREIGN KEY (firstName, lastName, departmentName) REFERENCES Faculty (firstName, lastName, departmentName) ON DELETE CASCADE ON UPDATE CASCADE);\n"
			+ "CREATE UNIQUE INDEX FacultyEmailIndex1 ON  FacultyEmail(firstName, lastName, departmentName, emailAddress);\n"
			+ "CREATE UNIQUE INDEX FacultyEmailIndex2 ON  FacultyEmail(facultyId, emailAddress);\n"
			+
			
			"CREATE TABLE OfficeHours (_id INTEGER PRIMARY KEY AUTOINCREMENT, courseId INTEGER REFERENCES Course(_id) ON DELETE CASCADE ON UPDATE CASCADE, facultyId INTEGER REFERENCES Faculty (_id) ON DELETE CASCADE ON UPDATE CASCADE, courseName TEXT, semesterName TEXT, firstName TEXT, lastName TEXT, departmentName TEXT, day INTEGER, startTime TEXT, endTime TEXT, location TEXT, FOREIGN KEY (courseName, semesterName) REFERENCES Course(name, semesterName) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (firstName, lastName, departmentName) REFERENCES Faculty(firstName, lastName, departmentName) ON DELETE CASCADE ON UPDATE CASCADE);\n"
			+ "CREATE UNIQUE INDEX OfficeHoursIndex1 ON OfficeHours(courseName, semesterName, firstName, lastName, departmentName, day, startTime, endTime);\n"
			+ "CREATE UNIQUE INDEX OfficeHoursIndex2 ON OfficeHours(courseId, facultyId, day, startTime, endTime);\n"
			+
			
			"CREATE TABLE CourseAlert (_id INTEGER PRIMARY KEY AUTOINCREMENT, courseId INTEGER REFERENCES Course(_id) ON DELETE CASCADE ON UPDATE CASCADE, courseName TEXT, semesterName TEXT, minutesBefore INTEGER, FOREIGN KEY (courseName, semesterName) REFERENCES Course(name, semesterName) ON DELETE CASCADE ON UPDATE CASCADE);\n"
			+ "CREATE UNIQUE INDEX CourseAlertIndex1 ON CourseAlert (courseName, semesterName, minutesBefore);\n"
			+ "CREATE UNIQUE INDEX CourseAlertIndex2 ON CourseAlert (courseId, minutesBefore);\n"
			+
			
			"CREATE TABLE TaskAlert (_id INTEGER PRIMARY KEY AUTOINCREMENT, taskId INTEGER REFERENCES Task(_id) ON DELETE CASCADE ON UPDATE CASCADE, taskName TEXT, courseName TEXT, semesterName TEXT, categoryName TEXT, minutesBefore INTEGER, FOREIGN KEY (taskName, courseName, semesterName, categoryName) REFERENCES Task (name, courseName, semesterName, categoryName) ON DELETE CASCADE ON UPDATE CASCADE);\n"
			+ "CREATE UNIQUE INDEX TaskAlertIndex1 ON TaskAlert (taskName, courseName, semesterName, categoryName, minutesBefore);\n"
			+ "CREATE UNIQUE INDEX TaskAlertIndex2 ON TaskAlert (taskId, categoryName, minutesBefore);\n"
			+
			
			"CREATE TABLE CourseTimeOverride (_id INTEGER PRIMARY KEY AUTOINCREMENT, courseId INTEGER REFERENCES Course(_id) ON DELETE CASCADE ON UPDATE CASCADE, courseName TEXT, semesterName TEXT, date INTEGER, startTimeHour INTEGER, startTimeMinute INTEGER, endTimeHour INTEGER, endTimeMinute INTEGER, FOREIGN KEY (courseName, semesterName) REFERENCES Course(name, semesterName) ON DELETE CASCADE ON UPDATE CASCADE);\n"
			+ "CREATE UNIQUE INDEX CourseTimeOverrideIndex1 ON CourseTimeOverride (courseName, semesterName, date, startTimeHour, startTimeMinute, endTimeHour, endTimeMinute);\n"
			+ "CREATE UNIQUE INDEX CourseTimeOverrideIndex2 ON CourseTimeOverride (courseId, date, startTimeHour, startTimeMinute, endTimeHour, endTimeMinute);\n"
			+
			
			"CREATE TABLE Holiday (_id INTEGER PRIMARY KEY AUTOINCREMENT, semesterId INTEGER REFERENCES Semester(_id) ON DELETE CASCADE ON UPDATE CASCADE, name TEXT, semesterName TEXT REFERENCES Semester(name) ON DELETE CASCADE ON UPDATE CASCADE, startDate INTEGER , endDate INTEGER);\n"
			+ "CREATE UNIQUE INDEX HolidayIndex1 ON Holiday (name, semesterName, startDate, endDate);\n"
			+ "CREATE UNIQUE INDEX HolidayIndex2 ON Holiday (_id, semesterId, startDate, endDate);\n"
			+
			
			"CREATE TABLE GradingScale (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT);\n"
			+ "CREATE UNIQUE INDEX GradingScaleIndex1 ON GradingScale (name);\n"
			+
			
			"CREATE TABLE GradingScaleRange (_id INTEGER PRIMARY KEY AUTOINCREMENT, letterGrade TEXT, minValue REAL, name TEXT REFERENCES GradingScale(name) ON DELETE CASCADE ON UPDATE CASCADE);	\r\n"
			+ "CREATE UNIQUE INDEX GradingScaleRangeIndex1 ON GradingScaleRange (letterGrade, minValue, name);\n"
			+
			
			"INSERT INTO GradingScale VALUES (null, 'Regular');\n"
			+ "INSERT INTO GradingScale VALUES (null, 'Plus-Minus');\n"
			+
			
			"INSERT INTO GradingScaleRange VALUES (null, 'A', 90.0, 'Regular');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'B', 80.0, 'Regular');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'C', 70.0, 'Regular');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'D', 60.0, 'Regular');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'F', 0, 'Regular');\n"
			+
			
			"INSERT INTO GradingScaleRange VALUES (null, 'A', 93.33, 'Plus-Minus');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'A-', 90.00, 'Plus-Minus');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'B+', 86.67, 'Plus-Minus');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'B', 83.33, 'Plus-Minus');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'B-', 80.00, 'Plus-Minus');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'C+', 76.67, 'Plus-Minus');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'C', 73.33, 'Plus-Minus');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'C-', 70.00, 'Plus-Minus');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'D+', 66.67, 'Plus-Minus');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'D', 63.33, 'Plus-Minus');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'D-', 60.00, 'Plus-Minus');\n"
			+ "INSERT INTO GradingScaleRange VALUES (null, 'F', 0, 'Plus-Minus');";
	
	/**
	 * The name of the database file on the file system.
	 */
	private static final String DATABASE_NAME = "BackpackEDU";
	
	/**
	 * The version of the database.
	 */
	private static final int DATABASE_VERSION = 1;
	
	/**
	 * The application context.
	 */
	private final Context context;
	
	/**
	 * XXX
	 * 
	 * @param context
	 *            the application context
	 */
	public BackpackEduDatabaseHelper(final Context context) {
		super(context,
				BackpackEduDatabaseHelper.DATABASE_NAME,
				null,
				BackpackEduDatabaseHelper.DATABASE_VERSION);
		this.context = context;
	}
	
	/**
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values for non-primary-key columns. Pass a null if you don't
	 *            have any values for these columns. Otherwise, create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the values before passing it. Refer to the Course class
	 *            in the TablesAndColumnsConstants package for all the column
	 *            names constants that you can use as the keys to your values
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addCourse(final String courseName,
			final String semesterName,
			ContentValues map) {
		long l = -1;
		if ((courseName != null)
				&& (semesterName != null)) {
			if (map == null) {
				map = new ContentValues();
			}
			
			final ContentValues criteria = new ContentValues();
			criteria.put(Semester.NAME,
					semesterName);
			final CursorSemester sems = this.getSemester(criteria,
					null,
					true);
			if (sems.getCount() != 1) {
				return false;
			}
			
			map.put(Course.SEMESTER_ID,
					sems.getColId());
			
			map.put(Course.NAME,
					courseName);
			map.put(Course.SEMESTER_NAME,
					semesterName);
			
			try {
				
				l = this.getWritableDatabase()
						.insert(Course.TABLE_NAME,
								null,
								map);
				
				// notification calls
				CursorCourse c = getCourse(map,
						null,
						false);
				(new RingerIntent(context)).setUpRingerChange(c);
				
				// close cursor
				c.close();
				
			} catch (final SQLException e) {
				Log.e("Error writing new Course",
						e.toString());
			} finally {
				sems.close();
			}
		}
		
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param minutesBefore
	 *            the number of minutes prior to the class to notify the user,
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addCourseAlert(final String courseName,
			final String semesterName,
			final Integer minutesBefore) {
		long l = -1;
		if ((courseName != null)
				&& (semesterName != null)
				&& (minutesBefore != null)) {
			final ContentValues map = new ContentValues();
			
			final ContentValues criteria = new ContentValues();
			criteria.put(Course.NAME,
					courseName);
			criteria.put(Course.SEMESTER_NAME,
					semesterName);
			final CursorCourse courses = this.getCourse(criteria,
					null,
					true);
			if (courses.getCount() != 1) {
				return false;
			}
			
			map.put(CourseAlert.COURSE_ID,
					courses.getColId());
			
			map.put(CourseAlert.COURSE_NAME,
					courseName);
			map.put(CourseAlert.SEMESTER_NAME,
					semesterName);
			map.put(CourseAlert.MINUTES_BEFORE,
					minutesBefore);
			try {
				
				l = this.getWritableDatabase()
						.insert(CourseAlert.TABLE_NAME,
								null,
								map);
				
				if (minutesBefore != null) {
					// notification calls
					ContentValues cVal = new ContentValues();
					cVal.put(Course.NAME,
							courseName);
					cVal.put(Course.SEMESTER_NAME,
							semesterName);
					CursorCourse c = getCourse(cVal,
							null,
							true);
					CursorCourseAlert ca = getCourseAlert(map,
							null,
							true);
					(new ReminderMngr(context)).setReminder(c,
							ca);
					
					// close cursors
					c.close();
					ca.close();
				}
				
			} catch (final SQLException e) {
				Log.e("Error writing new CourseAlert",
						e.toString());
			} finally {
				courses.close();
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param categoryName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values for non-primary-key columns. Pass a null if you don't
	 *            have any values for these columns. Otherwise, create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the values before passing it. Refer to the
	 *            CourseCategoryWeight class in the TablesAndColumnsConstants
	 *            package for all the column names constants that you can use as
	 *            the keys to your values
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addCourseCategoryWeight(final String courseName,
			final String semesterName,
			final String categoryName,
			ContentValues map) {
		long l = -1;
		if ((courseName != null)
				&& (semesterName != null)
				&& (categoryName != null)) {
			if (map == null) {
				map = new ContentValues();
			}
			
			final ContentValues criteria = new ContentValues();
			criteria.put(Course.NAME,
					courseName);
			criteria.put(Course.SEMESTER_NAME,
					semesterName);
			final CursorCourse courses = this.getCourse(criteria,
					null,
					true);
			if (courses.getCount() != 1) {
				return false;
			}
			
			map.put(CourseCategoryWeight.COURSE_ID,
					courses.getColId());
			
			map.put(CourseCategoryWeight.COURSE_NAME,
					courseName);
			map.put(CourseCategoryWeight.SEMESTER_NAME,
					semesterName);
			map.put(CourseCategoryWeight.CATEGORY_NAME,
					categoryName);
			
			try {
				
				l = this.getWritableDatabase()
						.insert(CourseCategoryWeight.TABLE_NAME,
								null,
								map);
			} catch (final SQLException e) {
				Log.e("Error writing new CourseCategoryWeight",
						e.toString());
			} finally {
				courses.close();
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param firstName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param lastName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param departmentName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values for non-primary-key columns. Pass a null if you don't
	 *            have any values for these columns. Otherwise, create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the values before passing it. Refer to the
	 *            CourseFaculty class in the TablesAndColumnsConstants package
	 *            for all the column names constants that you can use as the
	 *            keys to your values
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addCourseFaculty(final String courseName,
			final String semesterName,
			final String firstName,
			final String lastName,
			final String departmentName,
			ContentValues map) {
		long l = -1;
		if ((courseName != null)
				&& (semesterName != null)
				&& (firstName != null)
				&& (lastName != null)
				&& (departmentName != null)) {
			if (map == null) {
				map = new ContentValues();
			}
			
			ContentValues criteria = new ContentValues();
			criteria.put(Course.NAME,
					courseName);
			criteria.put(Course.SEMESTER_NAME,
					semesterName);
			final CursorCourse courses = this.getCourse(criteria,
					null,
					true);
			if (courses.getCount() != 1) {
				return false;
			}
			
			criteria = new ContentValues();
			criteria.put(Faculty.FIRST_NAME,
					firstName);
			criteria.put(Faculty.LAST_NAME,
					lastName);
			criteria.put(Faculty.DEPARTMENT_NAME,
					departmentName);
			final CursorFaculty faculties = this.getFaculty(criteria,
					null,
					true);
			if (faculties.getCount() != 1) {
				return false;
			}
			
			map.put(CourseFaculty.FACULTY_ID,
					faculties.getColId());
			map.put(CourseFaculty.COURSE_ID,
					courses.getColId());
			
			map.put(CourseFaculty.COURSE_NAME,
					courseName);
			map.put(CourseFaculty.SEMESTER_NAME,
					semesterName);
			map.put(CourseFaculty.FIRST_NAME,
					firstName);
			map.put(CourseFaculty.LAST_NAME,
					lastName);
			map.put(CourseFaculty.DEPARTMENT_NAME,
					departmentName);
			try {
				
				l = this.getWritableDatabase()
						.insert(CourseFaculty.TABLE_NAME,
								null,
								map);
			} catch (final SQLException e) {
				Log.e("Error writing new CourseFaculty",
						e.toString());
			} finally {
				courses.close();
				faculties.close();
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param day
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param startTime
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param endTime
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addCourseTimeOverride(final String courseName,
			final String semesterName,
			final long date,
			final int startTimeHour,
			final int startTimeMinute,
			final int endTimeHour,
			final int endTimeMinute) {
		long l = -1;
		if ((courseName != null)
				&& (semesterName != null)) {
			final ContentValues map = new ContentValues();
			
			final ContentValues criteria = new ContentValues();
			criteria.put(Course.NAME,
					courseName);
			criteria.put(Course.SEMESTER_NAME,
					semesterName);
			final CursorCourse courses = this.getCourse(criteria,
					null,
					true);
			if (courses.getCount() != 1) {
				return false;
			}
			
			map.put(CourseTimeOverride.COURSE_ID,
					courses.getColId());
			
			map.put(CourseTimeOverride.COURSE_NAME,
					courseName);
			map.put(CourseTimeOverride.SEMESTER_NAME,
					semesterName);
			map.put(CourseTimeOverride.DATE,
					Long.valueOf(date));
			map.put(CourseTimeOverride.START_TIME_HOUR,
					Integer.valueOf(startTimeHour));
			map.put(CourseTimeOverride.START_TIME_MINUTE,
					Integer.valueOf(startTimeMinute));
			map.put(CourseTimeOverride.END_TIME_HOUR,
					Integer.valueOf(endTimeHour));
			map.put(CourseTimeOverride.END_TIME_MINUTE,
					Integer.valueOf(endTimeMinute));
			try {
				
				l = this.getWritableDatabase()
						.insert(CourseTimeOverride.TABLE_NAME,
								null,
								map);
				
				// notification calls
				(new RingerIntent(context)).setUpRingerChange(courses);
				AllIntents.setUpCourseAlarms(this,
						context,
						courses);
				
			} catch (final SQLException e) {
				Log.e("Error writing new CourseTimeOverride",
						e.toString());
			} finally {
				courses.close();
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param departmentName
	 *            the department name, it's the primary key and therefore it
	 *            must not be null otherwise this method will return false
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addDepartment(final String departmentName) {
		long l = -1;
		if (departmentName != null) {
			final ContentValues map = new ContentValues();
			map.put(Department.NAME,
					departmentName);
			try {
				
				l = this.getWritableDatabase()
						.insert(Department.TABLE_NAME,
								null,
								map);
			} catch (final SQLException e) {
				Log.e("Error writing new Department",
						e.toString());
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param firstName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param lastName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param departmentName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values for non-primary-key columns. Pass a null if you don't
	 *            have any values for these columns. Otherwise, create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the values before passing it. Refer to the Faculty
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            values
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addFaculty(final String firstName,
			final String lastName,
			final String departmentName,
			ContentValues map) {
		long l = -1;
		if ((firstName != null)
				&& (lastName != null)
				&& (departmentName != null)) {
			if (map == null) {
				map = new ContentValues();
			}
			map.put(Faculty.FIRST_NAME,
					firstName);
			map.put(Faculty.LAST_NAME,
					lastName);
			map.put(Faculty.DEPARTMENT_NAME,
					departmentName);
			try {
				
				l = this.getWritableDatabase()
						.insert(Faculty.TABLE_NAME,
								null,
								map);
			} catch (final SQLException e) {
				Log.e("Error writing new Faculty",
						e.toString());
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param firstName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param lastName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param departmentName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param emailAddress
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values for non-primary-key columns. Pass a null if you don't
	 *            have any values for these columns. Otherwise, create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the values before passing it. Refer to the FacultyEmail
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            values
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addFacultyEmail(final String firstName,
			final String lastName,
			final String departmentName,
			final String emailAddress,
			ContentValues map) {
		long l = -1;
		if ((firstName != null)
				&& (lastName != null)
				&& (departmentName != null)
				&& (emailAddress != null)) {
			if (map == null) {
				map = new ContentValues();
			}
			
			final ContentValues criteria = new ContentValues();
			criteria.put(Faculty.FIRST_NAME,
					firstName);
			criteria.put(Faculty.LAST_NAME,
					lastName);
			criteria.put(Faculty.DEPARTMENT_NAME,
					departmentName);
			final CursorFaculty faculties = this.getFaculty(criteria,
					null,
					true);
			if (faculties.getCount() != 1) {
				return false;
			}
			
			map.put(FacultyEmail.FACULTY_ID,
					faculties.getColId());
			
			map.put(FacultyEmail.FIRST_NAME,
					firstName);
			map.put(FacultyEmail.LAST_NAME,
					lastName);
			map.put(FacultyEmail.DEPARTMENT_NAME,
					departmentName);
			map.put(FacultyEmail.EMAIL_ADDRESS,
					emailAddress);
			try {
				
				l = this.getWritableDatabase()
						.insert(FacultyEmail.TABLE_NAME,
								null,
								map);
			} catch (final SQLException e) {
				Log.e("Error writing new FacultyEmail",
						e.toString());
			} finally {
				faculties.close();
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param firstName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param lastName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param departmentName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param phoneNumber
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values for non-primary-key columns. Pass a null if you don't
	 *            have any values for these columns. Otherwise, create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the values before passing it. Refer to the FacultyPhone
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            values
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addFacultyPhone(final String firstName,
			final String lastName,
			final String departmentName,
			final String phoneNumber,
			ContentValues map) {
		long l = -1;
		if ((firstName != null)
				&& (lastName != null)
				&& (departmentName != null)
				&& (phoneNumber != null)) {
			if (map == null) {
				map = new ContentValues();
			}
			
			final ContentValues criteria = new ContentValues();
			criteria.put(Faculty.FIRST_NAME,
					firstName);
			criteria.put(Faculty.LAST_NAME,
					lastName);
			criteria.put(Faculty.DEPARTMENT_NAME,
					departmentName);
			final CursorFaculty faculties = this.getFaculty(criteria,
					null,
					true);
			if (faculties.getCount() != 1) {
				return false;
			}
			
			map.put(FacultyPhone.FACULTY_ID,
					faculties.getColId());
			
			map.put(FacultyPhone.FIRST_NAME,
					firstName);
			map.put(FacultyPhone.LAST_NAME,
					lastName);
			map.put(FacultyPhone.DEPARTMENT_NAME,
					departmentName);
			map.put(FacultyPhone.PHONE_NUMBER,
					phoneNumber);
			try {
				
				l = this.getWritableDatabase()
						.insert(FacultyPhone.TABLE_NAME,
								null,
								map);
			} catch (final SQLException e) {
				Log.e("Error writing new FacultyPhone",
						e.toString());
			} finally {
				faculties.close();
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param gradingScaleName
	 *            the name of the grading scale, for example, plus-minus Grading
	 *            or Regular Grading, primary key, must not be null otherwise
	 *            this method will return false
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addGradingScale(final String gradingScaleName) {
		long l = -1;
		if (gradingScaleName != null) {
			final ContentValues map = new ContentValues();
			map.put(GradingScale.NAME,
					gradingScaleName);
			try {
				
				l = this.getWritableDatabase()
						.insert(GradingScale.TABLE_NAME,
								null,
								map);
			} catch (final SQLException e) {
				Log.e("Error writing new GradingScale",
						e.toString());
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param gradingScaleName
	 *            the name of the grading scale, for example, plus-minus Grading
	 *            or Regular Grading, primary key, must not be null otherwise
	 *            this method will return false
	 * @param letterGrade
	 *            the letter grade to appear in the GradeCalc view, primary key,
	 *            must not be null otherwise this method will return false
	 * @param minValue
	 *            the minimum value to achieve the associated letter grade, for
	 *            example, 90 for A, primary key, must not be null otherwise
	 *            this method will return false
	 * @return
	 */
	public boolean addGradingScaleRange(final String gradingScaleName,
			final String letterGrade,
			final Double minValue) {
		long l = -1;
		if ((gradingScaleName != null)
				&& (letterGrade != null)
				&& (minValue != null)) {
			final ContentValues map = new ContentValues();
			map.put(GradingScaleRange.NAME,
					gradingScaleName);
			map.put(GradingScaleRange.LETTER_GRADE,
					letterGrade);
			map.put(GradingScaleRange.MIN_VALUE,
					minValue);
			try {
				
				l = this.getWritableDatabase()
						.insert(GradingScaleRange.TABLE_NAME,
								null,
								map);
			} catch (final SQLException e) {
				Log.e("Error writing new GradingScaleRange",
						e.toString());
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param holidayName
	 *            the name of the holiday, for example, Spring Break, primary
	 *            key, must not be null otherwise this method will return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param startDate
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param endDate
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addHoliday(final String holidayName,
			final String semesterName,
			final long startDate,
			final long endDate) {
		long l = -1;
		if ((holidayName != null)
				&& (semesterName != null)) {
			final ContentValues map = new ContentValues();
			
			final ContentValues criteria = new ContentValues();
			criteria.put(Semester.NAME,
					semesterName);
			final CursorSemester sems = this.getSemester(criteria,
					null,
					true);
			if (sems.getCount() != 1) {
				return false;
			}
			
			map.put(Holiday.SEMESTER_ID,
					sems.getColId());
			
			map.put(Holiday.NAME,
					holidayName);
			map.put(Holiday.SEMESTER_NAME,
					semesterName);
			map.put(Holiday.START_DATE,
					Long.valueOf(startDate));
			map.put(Holiday.END_DATE,
					Long.valueOf(endDate));
			try {
				
				l = this.getWritableDatabase()
						.insert(Holiday.TABLE_NAME,
								null,
								map);
				
				// TODO call notifications
				
			} catch (final SQLException e) {
				Log.e("Error writing new Holiday",
						e.toString());
			} finally {
				sems.close();
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param facultyFirstName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param facultyLastName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param facultyDepartmentName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param day
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param startTime
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param endTime
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values for non-primary-key columns. Pass a null if you don't
	 *            have any values for these columns. Otherwise, create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the values before passing it. Refer to the OfficeHours
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            values
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addOfficeHours(final String courseName,
			final String semesterName,
			final String facultyFirstName,
			final String facultyLastName,
			final String facultyDepartmentName,
			final Integer day,
			final String startTime,
			final String endTime,
			ContentValues map) {
		long l = -1;
		if ((courseName != null)
				&& (semesterName != null)
				&& (facultyFirstName != null)
				&& (facultyLastName != null)
				&& (facultyDepartmentName != null)
				&& (day != null)
				&& (startTime != null)
				&& (endTime != null)) {
			if (map == null) {
				map = new ContentValues();
			}
			
			ContentValues criteria = new ContentValues();
			criteria.put(Course.NAME,
					courseName);
			criteria.put(Course.SEMESTER_NAME,
					semesterName);
			final CursorCourse courses = this.getCourse(criteria,
					null,
					true);
			if (courses.getCount() != 1) {
				return false;
			}
			
			criteria = new ContentValues();
			criteria.put(Faculty.FIRST_NAME,
					facultyFirstName);
			criteria.put(Faculty.LAST_NAME,
					facultyLastName);
			criteria.put(Faculty.DEPARTMENT_NAME,
					facultyDepartmentName);
			final CursorFaculty faculties = this.getFaculty(criteria,
					null,
					true);
			if (faculties.getCount() != 1) {
				return false;
			}
			
			map.put(OfficeHours.FACULTY_ID,
					faculties.getColId());
			map.put(OfficeHours.COURSE_ID,
					courses.getColId());
			
			map.put(OfficeHours.COURSE_NAME,
					courseName);
			map.put(OfficeHours.SEMESTER_NAME,
					semesterName);
			map.put(OfficeHours.FIRST_NAME,
					facultyFirstName);
			map.put(OfficeHours.LAST_NAME,
					facultyLastName);
			map.put(OfficeHours.DEPARTMENT_NAME,
					facultyDepartmentName);
			map.put(OfficeHours.DAY,
					day);
			map.put(OfficeHours.START_TIME,
					startTime);
			map.put(OfficeHours.END_TIME,
					endTime);
			try {
				
				l = this.getWritableDatabase()
						.insert(OfficeHours.TABLE_NAME,
								null,
								map);
			} catch (final SQLException e) {
				Log.e("Error writing new OfficeHours",
						e.toString());
			} finally {
				faculties.close();
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addSemester(final String semesterName) {
		long l = -1;
		if (semesterName != null) {
			final ContentValues map = new ContentValues();
			map.put(Semester.NAME,
					semesterName);
			map.put(Semester.CREATION_DATE,
					System.currentTimeMillis());
			try {
				l = this.getWritableDatabase()
						.insert(Semester.TABLE_NAME,
								null,
								map);
			} catch (final SQLException e) {
				Log.e("Error writing new Semester",
						e.toString());
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param taskName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param categoryName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values for non-primary-key columns. Pass a null if you don't
	 *            have any values for these columns. Otherwise, create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the values before passing it. Refer to the Task class
	 *            in the TablesAndColumnsConstants package for all the column
	 *            names constants that you can use as the keys to your values
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addTask(final String taskName,
			final String courseName,
			final String semesterName,
			final String categoryName,
			ContentValues map) {
		long l = -1;
		if ((taskName != null)
				&& (courseName != null)
				&& (semesterName != null)
				&& (categoryName != null)) {
			if (map == null) {
				map = new ContentValues();
			}
			
			final ContentValues criteria = new ContentValues();
			criteria.put(Course.NAME,
					courseName);
			criteria.put(Course.SEMESTER_NAME,
					semesterName);
			final CursorCourse courses = this.getCourse(criteria,
					null,
					true);
			if (courses.getCount() != 1) {
				return false;
			}
			
			map.put(Task.COURSE_ID,
					courses.getColId());
			
			map.put(Task.NAME,
					taskName);
			map.put(Task.COURSE_NAME,
					courseName);
			map.put(Task.SEMESTER_NAME,
					semesterName);
			map.put(Task.CATEGORY_NAME,
					categoryName);
			try {
				
				l = this.getWritableDatabase()
						.insert(Task.TABLE_NAME,
								null,
								map);
			} catch (final SQLException e) {
				Log.e("Error writing new Task",
						e.toString());
			} finally {
				courses.close();
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param taskName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param categoryName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param minutesBefore
	 *            the number of minutes prior to the task to notify the user,
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true means the row was added, false means not added due to
	 *         duplication or because a null was passed to any of the primary
	 *         key parameter(s)
	 */
	public boolean addTaskAlert(final String taskName,
			final String courseName,
			final String semesterName,
			final String categoryName,
			final Integer minutesBefore) {
		long l = -1;
		if ((taskName != null)
				&& (courseName != null)
				&& (semesterName != null)
				&& (categoryName != null)
				&& (minutesBefore != null)) {
			final ContentValues map = new ContentValues();
			
			final ContentValues criteria = new ContentValues();
			criteria.put(Task.NAME,
					taskName);
			criteria.put(Task.COURSE_NAME,
					courseName);
			criteria.put(Task.SEMESTER_NAME,
					semesterName);
			criteria.put(Task.CATEGORY_NAME,
					categoryName);
			final CursorTask tasks = this.getTask(criteria,
					null,
					true);
			if (tasks.getCount() != 1) {
				tasks.close();
				return false;
			}
			
			map.put(TaskAlert.TASK_ID,
					tasks.getColId());
			
			map.put(TaskAlert.TASK_NAME,
					taskName);
			map.put(TaskAlert.COURSE_NAME,
					courseName);
			map.put(TaskAlert.SEMESTER_NAME,
					semesterName);
			map.put(TaskAlert.CATEGORY_NAME,
					categoryName);
			map.put(TaskAlert.MINUTES_BEFORE,
					minutesBefore);
			try {
				
				l = this.getWritableDatabase()
						.insert(TaskAlert.TABLE_NAME,
								null,
								map);
				
				// Notification calls
				final ContentValues val = new ContentValues();
				val.put(TaskAlert.TASK_ID,
						tasks.getColId());
				
				CursorTaskAlert ta = getTaskAlert(val,
						null,
						true);
				
				(new ReminderMngr(context)).setReminder(tasks,
						ta);
				ta.close();
				
			} catch (final SQLException e) {
				Log.e("Error writing new TaskAlert",
						e.toString());
			} finally {
				tasks.close();
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteCourse(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(Course.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			
			// notification calls
			ContentValues cVal = new ContentValues();
			cVal.put(Course.ID,
					id);
			CursorCourse c = getCourse(cVal,
					null,
					true);
			if (c.getCount() == 1) {
				c.moveToPosition(0);
				cVal.clear();
				cVal.put(Task.COURSE_ID,
						id);
				CursorTask t = getTask(cVal,
						null,
						true);
				BackpackEduDatabaseHelper db = this;
				if (t.getCount() > 0) {
					for (int i = 0; i < t.getCount(); i++) {
						t.moveToPosition(i);
						(new AllIntents()).cancelTaskAlarms(db,
								context,
								t);
					}
					
				}
				
				// close cursors
				c.close();
				t.close();
				
			}
			
			result = (this.getWritableDatabase()
					.delete(Course.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
		} catch (final SQLException e) {
			Log.e("Error deleting Course",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param minutesBefore
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteCourseAlert(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(CourseAlert.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			
			// notification calls
			ContentValues cVal = new ContentValues();
			cVal.put(CourseAlert.ID,
					id);
			CursorCourseAlert ca = getCourseAlert(cVal,
					null,
					true);
			if (ca.getCount() == 1) {
				ca.moveToPosition(0);
				cVal.clear();
				cVal.put(Course.ID,
						ca.getColCourseId());
				CursorCourse c = getCourse(cVal,
						null,
						true);
				BackpackEduDatabaseHelper db = this;
				
				(new ReminderMngr(context)).cancelReminder(c,
						ca);
				
				// close cursors
				c.close();
				
			}
			ca.close();
			
			result = (this.getWritableDatabase()
					.delete(CourseAlert.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
		} catch (final SQLException e) {
			Log.e("Error deleting CourseAlert",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param categoryName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteCourseCategoryWeight(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(CourseCategoryWeight.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			
			// notification calls
			CursorCourseCategoryWeight ccw = getCourseCategoryWeight(map,
					null,
					true);
			if (ccw.getCount() == 1) {
				ccw.moveToPosition(0);
				ContentValues cVal = new ContentValues();
				cVal.put(Task.CATEGORY_NAME,
						ccw.getColCategoryName());
				CursorTask t = getTask(cVal,
						null,
						true);
				BackpackEduDatabaseHelper db = this;
				if (t.getCount() > 0) {
					for (int i = 0; i < t.getCount(); i++) {
						t.moveToPosition(i);
						(new AllIntents()).cancelTaskAlarms(db,
								context,
								t);
					}
					
				}
				
				// close cursors
				ccw.close();
				t.close();
				
			}
			
			result = (this.getWritableDatabase()
					.delete(CourseCategoryWeight.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
		} catch (final SQLException e) {
			Log.e("Error deleting CourseCategoryWeight",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param firstName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param lastName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param departmentName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteCourseFaculty(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(CourseFaculty.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			result = (this.getWritableDatabase()
					.delete(CourseFaculty.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
		} catch (final SQLException e) {
			Log.e("Error deleting CourseFaculty",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param day
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param startTime
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param endTime
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteCourseTimeOverride(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(CourseTimeOverride.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			
			result = (this.getWritableDatabase()
					.delete(CourseTimeOverride.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
			
			if (result) {
				// notification calls
				CursorCourse c = getCourse(map,
						null,
						false);
				(new RingerIntent(context)).setUpRingerChange(c);
				AllIntents.setUpCourseAlarms(this,
						context,
						c);
				
				// close cursor
				c.close();
			}
			
		} catch (final SQLException e) {
			Log.e("Error deleting CourseTimeOverride",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param departmentName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteDepartment(final String departmentName) {
		boolean result = false;
		if (departmentName != null) {
			
			final ContentValues map = new ContentValues();
			map.put(Department.NAME,
					departmentName);
			
			final String[] args = new String[map.size()];
			final String whereClause = this.parseCriteria("",
					args,
					map);
			
			try {
				result = (this.getWritableDatabase()
						.delete(Department.TABLE_NAME,
								whereClause,
								args) == 0
						? false
						: true);
			} catch (final SQLException e) {
				Log.e("Error deleting Department",
						e.toString());
			}
		}
		return result;
	}
	
	/**
	 * @param firstName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param lastName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param departmentName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteFaculty(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(Faculty.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			result = (this.getWritableDatabase()
					.delete(Faculty.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
		} catch (final SQLException e) {
			Log.e("Error deleting Faculty",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param firstName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param lastName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param departmentName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param emailAddress
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteFacultyEmail(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(FacultyEmail.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			result = (this.getWritableDatabase()
					.delete(FacultyEmail.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
		} catch (final SQLException e) {
			Log.e("Error deleting FacultyEmail",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param firstName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param lastName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param departmentName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param phoneNumber
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteFacultyPhone(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(FacultyPhone.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			result = (this.getWritableDatabase()
					.delete(FacultyPhone.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
		} catch (final SQLException e) {
			Log.e("Error deleting FacultyPhone",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param gradingScaleName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteGradingScale(final String gradingScaleName) {
		boolean result = false;
		if (gradingScaleName != null) {
			
			final ContentValues map = new ContentValues();
			map.put(GradingScale.NAME,
					gradingScaleName);
			
			final String[] args = new String[map.size()];
			final String whereClause = this.parseCriteria("",
					args,
					map);
			
			try {
				result = (this.getWritableDatabase()
						.delete(GradingScale.TABLE_NAME,
								whereClause,
								args) == 0
						? false
						: true);
			} catch (final SQLException e) {
				Log.e("Error deleting GradingScale",
						e.toString());
			}
		}
		return result;
	}
	
	/**
	 * @param gradingScaleName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param letterGrade
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param minValue
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteGradingScaleRange(final String gradingScaleName,
			final String letterGrade,
			final Double minValue) {
		boolean result = false;
		if ((gradingScaleName != null)
				&& (letterGrade != null)
				&& (minValue != null)) {
			
			final ContentValues map = new ContentValues();
			map.put(GradingScaleRange.NAME,
					gradingScaleName);
			map.put(GradingScaleRange.LETTER_GRADE,
					letterGrade);
			map.put(GradingScaleRange.MIN_VALUE,
					minValue);
			
			final String[] args = new String[map.size()];
			final String whereClause = this.parseCriteria("",
					args,
					map);
			
			try {
				result = (this.getWritableDatabase()
						.delete(GradingScaleRange.TABLE_NAME,
								whereClause,
								args) == 0
						? false
						: true);
			} catch (final SQLException e) {
				Log.e("Error deleting GradingScaleRange",
						e.toString());
			}
		}
		return result;
	}
	
	/**
	 * @param holidayName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param startDate
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param endDate
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteHoliday(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(Holiday.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			result = (this.getWritableDatabase()
					.delete(Holiday.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
		} catch (final SQLException e) {
			Log.e("Error deleting Holiday",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param facultyFirstName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param facultyLastName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param facultyDepartmentName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param day
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param startTime
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param endTime
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteOfficeHours(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(OfficeHours.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			result = (this.getWritableDatabase()
					.delete(OfficeHours.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
		} catch (final SQLException e) {
			Log.e("Error deleting OfficeHours",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteSemester(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(Semester.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			result = (this.getWritableDatabase()
					.delete(Semester.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
		} catch (final SQLException e) {
			Log.e("Error deleting Semester",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param taskName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param categoryName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteTask(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(Task.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			
			// Notification calls
			CursorTask tasks = getTask(map,
					null,
					true);
			if (tasks.getCount() == 1) {
				tasks.moveToPosition(0);
				ContentValues val = new ContentValues();
				val.put(TaskAlert.TASK_ID,
						tasks.getColId());
				
				(new AllIntents()).cancelTaskAlarms(this,
						context,
						tasks);
				
			}
			tasks.close();
			
			result = (this.getWritableDatabase()
					.delete(Task.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
		} catch (final SQLException e) {
			Log.e("Error deleting Task",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param taskName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param courseName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param semesterName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param categoryName
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @param minutesBefore
	 *            primary key, must not be null otherwise this method will
	 *            return false
	 * @return true if the record was deleted, false if no such record exists
	 */
	public boolean deleteTaskAlert(final long id) {
		boolean result = false;
		
		final ContentValues map = new ContentValues();
		map.put(TaskAlert.ID,
				id);
		
		final String[] args = new String[map.size()];
		final String whereClause = this.parseCriteria("",
				args,
				map);
		
		try {
			
			// notification calls
			CursorTaskAlert ta = getTaskAlert(map,
					null,
					true);
			if (ta.getCount() == 1) {
				ContentValues val = new ContentValues();
				val.put(Task.ID,
						ta.getColTaskId());
				CursorTask tasks = getTask(val,
						null,
						true);
				(new ReminderMngr(context)).cancelReminder(tasks,
						ta);
				tasks.close();
				
			}
			ta.close();
			
			result = (this.getWritableDatabase()
					.delete(TaskAlert.TABLE_NAME,
							whereClause,
							args) == 0
					? false
					: true);
			
		} catch (final SQLException e) {
			Log.e("Error deleting TaskAlert",
					e.toString());
		}
		return result;
	}
	
	/**
	 * @param courseName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param semesterName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editCourse(final long id,
			final ContentValues map) {
		long l = -1;
		if (map != null) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(Course.ID,
						id);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(Course.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
					// notification calls
					if (map.containsKey(Course.START_TIME_HOUR)
							|| map.containsKey(Course.START_TIME_MINUTE)
							|| map.containsKey(Course.DAY_BIT_FIELD)) {
						CursorCourse c = getCourse(primary,
								null,
								true);
						(new AllIntents()).setUpCourseAlarms(new BackpackEduDatabaseHelper(null),
								context,
								c);
						c.close();
					}
					
				} catch (final SQLException e) {
					Log.e("Error editing Course",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param courseName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param semesterName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param minutesBefore
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editCourseAlert(final long id,
			final ContentValues map) {
		long l = -1;
		if (map != null) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(CourseAlert.ID,
						id);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					if (map.containsKey(CourseAlert.MINUTES_BEFORE)) {
						// notification calls
						ContentValues cVal = new ContentValues();
						cVal.put(CourseAlert.ID,
								id);
						CursorCourseAlert ca = getCourseAlert(cVal,
								null,
								true);
						if (ca.getCount() == 1) {
							ca.moveToPosition(0);
							cVal.clear();
							cVal.put(Course.ID,
									ca.getColCourseId());
							CursorCourse c = getCourse(cVal,
									null,
									true);
							(new ReminderMngr(context)).setReminder(c,
									ca);
							c.close();
						}
						
						// close cursors
						ca.close();
					}
					
					l = this.getWritableDatabase()
							.update(CourseAlert.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					Log.e("Error editing CourseAlert",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param courseName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param semesterName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param categoryName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editCourseCategoryWeight(final long id,
			final ContentValues map) {
		long l = -1;
		if (map != null) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(CourseCategoryWeight.ID,
						id);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(CourseCategoryWeight.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					Log.e("Error editing CourseCategoryWeight",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param courseName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param semesterName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param firstName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param lastName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param departmentName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editCourseFaculty(final String courseName,
			final String semesterName,
			final String firstName,
			final String lastName,
			final String departmentName,
			final ContentValues map) {
		long l = -1;
		if ((courseName != null)
				&& (semesterName != null)
				&& (firstName != null)
				&& (lastName != null)
				&& (departmentName != null)
				&& (map != null)) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(CourseFaculty.COURSE_NAME,
						courseName);
				primary.put(CourseFaculty.SEMESTER_NAME,
						semesterName);
				primary.put(CourseFaculty.FIRST_NAME,
						firstName);
				primary.put(CourseFaculty.LAST_NAME,
						lastName);
				primary.put(CourseFaculty.DEPARTMENT_NAME,
						departmentName);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(CourseFaculty.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					Log.e("Error editing CourseFaculty",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param courseName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param semesterName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param day
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param startTime
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param endTime
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editCourseTimeOverride(final long id,
			final ContentValues map) {
		long l = -1;
		if (map != null) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(CourseTimeOverride.ID,
						id);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(CourseTimeOverride.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					Log.e("Error editing CourseTimeOverride",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param departmentName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editDepartment(final String departmentName,
			final ContentValues map) {
		long l = -1;
		if ((departmentName != null)
				&& (map != null)) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(Department.NAME,
						departmentName);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(Department.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					Log.e("Error editing Department",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param firstName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param lastName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param departmentName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editFaculty(final long id,
			final ContentValues map) {
		long l = -1;
		if (map != null) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(Faculty.ID,
						id);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(Faculty.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					Log.e("Error editing Faculty",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param firstName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param lastName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param departmentName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param emailAddress
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editFacultyEmail(final long id,
			final ContentValues map) {
		long l = -1;
		if (map != null) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(FacultyEmail.ID,
						id);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(FacultyEmail.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					Log.e("Error editing FacultyEmail",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param firstName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param lastName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param departmentName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param phoneNumber
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editFacultyPhone(final long id,
			final ContentValues map) {
		long l = -1;
		if (map != null) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(FacultyPhone.ID,
						id);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(FacultyPhone.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					Log.e("Error editing FacultyPhone",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param gradingScaleName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editGradingScale(final String gradingScaleName,
			final ContentValues map) {
		long l = -1;
		if ((gradingScaleName != null)
				&& (map != null)) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(GradingScale.NAME,
						gradingScaleName);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(GradingScale.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					Log.e("Error editing GradingScale",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param gradingScaleName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param letterGrade
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param minValue
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s)(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editGradingScaleRange(final String gradingScaleName,
			final String letterGrade,
			final Double minValue,
			final ContentValues map) {
		long l = -1;
		if ((gradingScaleName != null)
				&& (letterGrade != null)
				&& (minValue != null)
				&& (map != null)) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(GradingScaleRange.NAME,
						gradingScaleName);
				primary.put(GradingScaleRange.LETTER_GRADE,
						letterGrade);
				primary.put(GradingScaleRange.MIN_VALUE,
						minValue);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(GradingScaleRange.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					Log.e("Error editing GradingScaleRange",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param holidayName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param semesterName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param startDate
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param endDate
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editHoliday(final long id,
			final ContentValues map) {
		long l = -1;
		if (map != null) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(Holiday.ID,
						id);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(Holiday.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					Log.e("Error editing Holiday",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param courseName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param semesterName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param facultyFirstName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param facultyLastName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param facultyDepartmentName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param day
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param startTime
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param endTime
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editOfficeHours(final long id,
			final ContentValues map) {
		long l = -1;
		if (map != null) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(OfficeHours.ID,
						id);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(OfficeHours.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					Log.e("Error editing OfficeHours",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param semesterName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editSemester(final long id,
			final ContentValues map) {
		long l = -1;
		
		if (map != null) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(Semester.ID,
						id);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(Semester.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
				} catch (final SQLException e) {
					
					Log.e("Error editing Semester",
							e.toString());
					
				}
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param taskName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param courseName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param semesterName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param categoryName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editTask(final long id,
			final ContentValues map) {
		long l = -1;
		if (map != null) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(Task.ID,
						id);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(Task.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
					// notification calls
					if (map.containsKey(Task.IS_COMPLETED)) {
						final ContentValues cVal = new ContentValues();
						cVal.put(Task.ID,
								id);
						final CursorTask t = this.getTask(cVal,
								null,
								true);
						AllIntents.cancelTaskAlarms(this,
								this.context,
								t);
						t.close();
						
					} else if (map.containsKey(Task.DATE_DUE)) {
						final ContentValues cVal = new ContentValues();
						cVal.put(Task.ID,
								id);
						final CursorTask t = this.getTask(cVal,
								null,
								true);
						AllIntents.setUpTaskAlarms(this,
								this.context,
								t);
						t.close();
					}
					
				} catch (final SQLException e) {
					Log.e("Error editing Task",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param taskName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param courseName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param semesterName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param categoryName
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param minutesBefore
	 *            primary key, used to find the row that you want to edit, must
	 *            not be null otherwise the method will return false
	 * @param map
	 *            A ContentValues object (which is like a map) used to pass in
	 *            new values for the row that you want to edit. You create a new
	 *            ContentValues object and use its "put" method (overloaded) to
	 *            put in the new values before passing it. Refer to the Semester
	 *            class in the TablesAndColumnsConstants package for all the
	 *            column names constants that you can use as the keys to your
	 *            new values
	 * @return true means the row was successfully edited, false means nothing
	 *         was changed due to passing null(s) to the method or the record
	 *         does not exist in the database
	 */
	public boolean editTaskAlert(final long id,
			final ContentValues map) {
		long l = -1;
		if (map != null) {
			if (map.size() > 0) {
				
				final ContentValues primary = new ContentValues();
				primary.put(TaskAlert.ID,
						id);
				
				final String[] whereArgs = new String[primary.size()];
				final String whereClause = this.parseCriteria("",
						whereArgs,
						primary);
				
				try {
					
					l = this.getWritableDatabase()
							.update(TaskAlert.TABLE_NAME,
									map,
									whereClause,
									whereArgs);
					
					
					
					// Notification calls
					final ContentValues val = new ContentValues();
					val.put(TaskAlert.ID, id);
					CursorTaskAlert ta = getTaskAlert(val, null, true);
					if (ta.getCount() > 0) {
						val.clear();
						val.put(Task.ID,
								ta.getColTaskId());
						
						CursorTask t = getTask (val,
								null,
								true);
						
						(new ReminderMngr(context)).setReminder(t,
								ta);
						ta.close();
						t.close();
					}
					
					
					
					
					
				} catch (final SQLException e) {
					Log.e("Error editing TaskAlert",
							e.toString());
				}
				
			}
		}
		return l == -1
				? false
				: true;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to Course class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorCourse getCourse(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorCourse.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorCourse c = (CursorCourse) d.rawQueryWithFactory(new CursorCourse.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to CourseAlert class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorCourseAlert getCourseAlert(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorCourseAlert.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorCourseAlert c = (CursorCourseAlert) d.rawQueryWithFactory(new CursorCourseAlert.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to CourseCategoryWeight class
	 *            in the TablesAndColumnsConstants package for all the column
	 *            names constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorCourseCategoryWeight getCourseCategoryWeight(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorCourseCategoryWeight.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorCourseCategoryWeight c = (CursorCourseCategoryWeight) d.rawQueryWithFactory(new CursorCourseCategoryWeight.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to CourseFaculty class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorCourseFaculty getCourseFaculty(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorCourseFaculty.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorCourseFaculty c = (CursorCourseFaculty) d.rawQueryWithFactory(new CursorCourseFaculty.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	public CursorCoursesForAgendaView getCoursesForAgendaView(final long leftBound,
			final long rightBound) {
		CursorCoursesForAgendaView c = null;
		final String sql = "SELECT "
				+ Course.NAME
				+ ", "
				+ Course.ID
				+ ", "
				+ Course.SEMESTER_ID
				+ ", CASE WHEN (startDate > "
				+ leftBound
				+ ") THEN startDate ELSE "
				+ leftBound
				+ " END AS startDate, CASE WHEN (endDate < "
				+ rightBound
				+ ") THEN endDate ELSE "
				+ rightBound
				+ " END AS endDate, startTimeHour, startTimeMinute, endTimeHour, endTimeMinute, dayBitField FROM Course WHERE startTimeHour IS NOT null AND startTimeMinute IS NOT NULL AND endTimeHour IS NOT null AND endTimeMinute IS NOT null AND dayBitField <> 0 AND startDate < "
				+ rightBound
				+ " AND endDate >= "
				+ leftBound
				+ ";";
		c = (CursorCoursesForAgendaView) this.getReadableDatabase()
				.rawQueryWithFactory(new CursorCoursesForAgendaView.Factory(),
						sql,
						null,
						null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to CourseTimeOverride class in
	 *            the TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorCourseTimeOverride getCourseTimeOverride(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorCourseTimeOverride.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorCourseTimeOverride c = (CursorCourseTimeOverride) d.rawQueryWithFactory(new CursorCourseTimeOverride.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	public CursorCourseTimeOverride getCourseTimeOverridesForAgendaView(final long leftBound,
			final long rightBound) {
		CursorCourseTimeOverride c = null;
		final String sql = "SELECT * from CourseTimeOverride WHERE "
				+ CourseTimeOverride.DATE
				+ " >= "
				+ leftBound
				+ " AND "
				+ CourseTimeOverride.DATE
				+ " < "
				+ rightBound
				+ " ORDER BY "
				+ CourseTimeOverride.DATE
				+ ";";
		c = (CursorCourseTimeOverride) this.getReadableDatabase()
				.rawQueryWithFactory(new CursorCourseTimeOverride.Factory(),
						sql,
						null,
						null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to Department class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorDepartment getDepartment(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorDepartment.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorDepartment c = (CursorDepartment) d.rawQueryWithFactory(new CursorDepartment.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to Faculty class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorFaculty getFaculty(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorFaculty.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorFaculty c = (CursorFaculty) d.rawQueryWithFactory(new CursorFaculty.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to FacultyEmail class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorFacultyEmail getFacultyEmail(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorFacultyEmail.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorFacultyEmail c = (CursorFacultyEmail) d.rawQueryWithFactory(new CursorFacultyEmail.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to FacultyPhone class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorFacultyPhone getFacultyPhone(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorFacultyPhone.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorFacultyPhone c = (CursorFacultyPhone) d.rawQueryWithFactory(new CursorFacultyPhone.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to GradingScale class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorGradingScale getGradingScale(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorGradingScale.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorGradingScale c = (CursorGradingScale) d.rawQueryWithFactory(new CursorGradingScale.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to GradingScaleRange class in
	 *            the TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorGradingScaleRange getGradingScaleRange(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorGradingScaleRange.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorGradingScaleRange c = (CursorGradingScaleRange) d.rawQueryWithFactory(new CursorGradingScaleRange.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to Holiday class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorHoliday getHoliday(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorHoliday.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorHoliday c = (CursorHoliday) d.rawQueryWithFactory(new CursorHoliday.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	public CursorHoliday getHolidaysForAgendaView(final long leftBound,
			final long rightBound) {
		CursorHoliday c = null;
		final String sql = "SELECT "
				+ Holiday.NAME
				+ ", "
				+ Holiday.SEMESTER_ID
				+ ", CASE WHEN (startDate > "
				+ leftBound
				+ ") THEN startDate ELSE "
				+ leftBound
				+ " END AS startDate, CASE WHEN (endDate < "
				+ rightBound
				+ ") THEN endDate ELSE "
				+ rightBound
				+ " END AS endDate FROM Holiday WHERE startDate < "
				+ rightBound
				+ " AND endDate >= "
				+ leftBound
				+ ";";
		c = (CursorHoliday) this.getReadableDatabase()
				.rawQueryWithFactory(new CursorHoliday.Factory(),
						sql,
						null,
						null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to OfficeHours class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorOfficeHours getOfficeHours(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorOfficeHours.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorOfficeHours c = (CursorOfficeHours) d.rawQueryWithFactory(new CursorOfficeHours.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to Semester class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorSemester getSemester(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorSemester.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorSemester c = (CursorSemester) d.rawQueryWithFactory(new CursorSemester.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to Task class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorTask getTask(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorTask.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorTask c = (CursorTask) d.rawQueryWithFactory(new CursorTask.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * @param criteria
	 *            A ContentValues object (which is like a map) used to pass in
	 *            values that you want to search for. Pass a null if you want
	 *            all rows in the table. Otherwise, create a new ContentValues
	 *            object and use its "put" method (overloaded) to put in the
	 *            values before passing it. Refer to TaskAlert class in the
	 *            TablesAndColumnsConstants package for all the column names
	 *            constants that you can use as the keys to your values
	 * @param sortBy
	 *            A String array of column names that you want your returned
	 *            dataset sorted by.
	 * @return For example, getCourse(null, new String[]{Course.SEMESTER_NAME,
	 *         Course.NAME}) will return a Cursor object that contains all the
	 *         courses in the Course table sorted by semester name and then by
	 *         course name
	 */
	public CursorTaskAlert getTaskAlert(final ContentValues criteria,
			final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorTaskAlert.QUERY;
		String[] args = null;
		if (criteria != null) {
			if (criteria.size() > 0) {
				args = new String[criteria.size()];
				sql = this.parseCriteria(sql
						+ " where ",
						args,
						criteria);
			}
		}
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorTaskAlert c = (CursorTaskAlert) d.rawQueryWithFactory(new CursorTaskAlert.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	public CursorTaskForAgendaView getTasksForAgendaView(final Long fromDueDate) {
		CursorTaskForAgendaView c = null;
		if (fromDueDate != null) {
			
			final String[] args = new String[] { fromDueDate.toString() };
			String sql = "SELECT "
					+ Task.COURSE_ID
					+ ", "
					+ Task.COURSE_NAME
					+ ", "
					+ Task.DATE_DUE
					+ ", "
					+ Task.ID
					+ ", "
					+ Task.IS_COMPLETED
					+ ", "
					+ Task.NAME
					+ " FROM "
					+ Task.TABLE_NAME
					+ " WHERE "
					+ Task.IS_COMPLETED
					+ " IS NOT 1 AND "
					+ Task.DATE_DUE
					+ " >= ? ";
			sql += " ORDER BY "
					+ Task.DATE_DUE;
			c = (CursorTaskForAgendaView) this.getReadableDatabase()
					.rawQueryWithFactory(new CursorTaskForAgendaView.Factory(),
							sql,
							args,
							null);
			c.moveToFirst();
		}
		return c;
	}
	
	public CursorUniqueFacultyType getUniqueFacultyTypes(final String[] sortBy,
			final boolean isAscending) {
		String sql = CursorUniqueFacultyType.QUERY;
		final String[] args = null;
		
		if (sortBy != null) {
			if (sortBy.length > 0) {
				sql = this.parseSortBy(sql
						+ " order by ",
						sortBy);
				if (!isAscending) {
					sql += " DESC";
				}
			}
		}
		
		final SQLiteDatabase d = this.getReadableDatabase();
		final CursorUniqueFacultyType c = (CursorUniqueFacultyType) d.rawQueryWithFactory(new CursorUniqueFacultyType.Factory(),
				sql,
				args,
				null);
		c.moveToFirst();
		return c;
	}
	
	/**
	 * XXX
	 * 
	 * @param db
	 */
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * android.database.sqlite.SQLiteOpenHelper#onCreate(android.database.sqlite
	 * .SQLiteDatabase)
	 */
	@Override
	public void onCreate(final SQLiteDatabase db) {
		this.createDatabase(db);
	}
	
	/**
	 * XXX
	 * 
	 * @param db
	 */
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * android.database.sqlite.SQLiteOpenHelper#onOpen(android.database.sqlite
	 * .SQLiteDatabase)
	 */
	@Override
	public void onOpen(final SQLiteDatabase db) {
		super.onOpen(db);
		try {
			db.execSQL("PRAGMA foreign_keys = ON");
		} catch (final SQLException ex) {
			Log.e("Cannot enable foreign key!",
					ex.toString()); // XXX should be
									// tag instead
		}
	}
	
	/**
	 * XXX
	 * 
	 * @param db
	 * @param oldVersion
	 * @param newVersion
	 */
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * android.database.sqlite.SQLiteOpenHelper#onUpgrade(android.database.sqlite
	 * .SQLiteDatabase, int, int)
	 */
	@Override
	public void onUpgrade(final SQLiteDatabase db,
			final int oldVersion,
			final int newVersion) {
		/*
		 * Each time we upgrade the database, we have to write an upgrade script
		 * for the current version. This might be accomplished using a switch
		 * statement with fall-through cases. We'll also have to figure out
		 * where to start based on the oldVersion param.
		 */
	}
	
	/**
	 * XXX
	 * 
	 * @param db
	 */
	private void createDatabase(final SQLiteDatabase db) {
		final String[] sql = BackpackEduDatabaseHelper.dbInitilizer.split("\n");
		db.beginTransaction();
		try {
			// Create tables & test data
			this.execMultipleSQL(db,
					sql);
			db.setTransactionSuccessful();
		} catch (final SQLException ex) {
			Log.e("Error creating tables and debug data ",
					ex.toString());
		} finally {
			db.endTransaction();
		}
	}
	
	private void execMultipleSQL(final SQLiteDatabase db,
			final String[] sql) {
		for (final String s : sql) {
			if (s.trim()
					.length() > 0) {
				db.execSQL(s);
			}
		}
	}
	
	private String parseCriteria(final String initialString,
			final String[] args,
			final ContentValues criteria) {
		String result = initialString;
		final Set<Entry<String, Object>> s = criteria.valueSet();
		
		int i = 0;
		for (final Entry<String, Object> entry : s) {
			result += entry.getKey()
					+ " = ? and ";
			args[i++] = entry.getValue()
					.toString();
		}
		result = result.substring(0,
				result.length() - 4);
		return result;
	}
	
	private String parseSortBy(final String sql,
			final String[] sortBy) {
		String result = sql;
		for (final String s : sortBy) {
			result += s
					+ ", ";
		}
		result = result.substring(0,
				result.length() - 2);
		return result;
	}
	
}
